package Model;

import java.awt.Point;
import java.awt.event.KeyEvent;
import java.util.*;

import Controller.ButtonHandler;
import Main.FlummoxMain;
import Model.*;
import View.*;

public class GameAI {

	// Globals to be used when moving
	public static final String UP = "UP";
	public static final String DOWN = "DOWN";
	public static final String LEFT = "LEFT";
	public static final String RIGHT = "RIGHT";

	// global variables for a monster's movements
	public static final int RANDOM_MOVE = 0;
	public static final int CHASE_MOVE = 1;
	public static final int FLEEING_MOVE = 2;

	// Global for no items check
	public static final int NO_ITEMS = 0;

	private static GraphicalView gameView;
	private static boolean gameOver;
	private int trapsLeft;
	private boolean wantToTrap;
	private static int hopsLeft;


	private static Game myGame;

	// based on the gametype entered generate the maze specific to the
	// game
	public GameAI(int gameType,Game game) {
		// based on the gameType set up the right data
		// ...


		switch (gameType) {
		case Game.PACMAN_GAME:
			newGame((Game.PACMAN_GAME));
		case Game.MOUSE_GAME:
		case Game.BUNNY_GAME:
		}
        myGame = game;
	}


	// Standard newgame for implementing game without levels
	public static void newGame() {
		gameOver = false;
	}

	// New Game implementing game with levels
	public void newGame(int gametype) {
		gameOver = false;
	}

	public static void reset() {

	}

	public boolean isGameOver() {
		return gameOver;
	}

	public static void play() {

	}

	

	public void setGame(Game newGame) {
		myGame = newGame;
	}

	public Game getGame() {
		return myGame;
	}

	

	// places a trap at cuurentSpot
	public void placeTrap(Point currentSpot) {

	}

	public int getTrapsPlaced() {
		return trapsLeft;
	}

	// gets set when player presses enter traps for GameAI
	public void setWantToTrap(boolean iWant) {
		wantToTrap = iWant;
	}

	// getHopLeft
	public int getHopsLeft() {
		return hopsLeft;
	}

	// Game will want to reset bunnies hopsLeft
	// either for new game or in-game action
	public void setHopsLeft(int newHops) {
		hopsLeft = newHops;
	}

	// checks traps for GameAI
	public boolean doesWantToTrap() {
		return wantToTrap;
	}

	// move the monster randomly
	public void moveMonster(Monster m) {
		Random numbergenerator = new Random();
		int number = numbergenerator.nextInt(3);
		Point p = new Point();
		p.x = m.getCoordinateX();
		p.y = m.getCoordinateY();
		if (number == 0) {
			if (canMove(m, new Point(p.x, (p.y - 1)))) {
				moveMonsterUp(m);
			}
			
		} else if (number == 1) {
			if (canMove(m, new Point(p.x, (p.y + 1)))) {
				moveMonsterDown(m);
			}
		} else if (number == 2) {
			if (canMove(m, new Point((p.x + 1), p.y))) {
				moveMonsterRight(m);
			}
		} else if (number == 3) {
			if (canMove(m, new Point((p.x - 1), p.y))) {
				moveMonsterLeft(m);
			}
		}
	}

	public void moveMonsterLeft(Monster m) {
		m.setCoordinateX(m.getCoordinateX() - 1);
	}

	public void moveMonsterRight(Monster m) {
		m.setCoordinateX(m.getCoordinateX() + 1);
	}

	public void moveMonsterDown(Monster m) {
		m.setCoordinateX(m.getCoordinateY() + 1);
	}

	public void moveMonsterUp(Monster m) {
		m.setCoordinateX(m.getCoordinateY() - 1);
	}

	// move the monster given a specific move type
	public void moveMonster(int moveType, Monster m) {
		if (moveType == RANDOM_MOVE) {
			moveMonster(m);
		} else if (moveType == CHASE_MOVE) {
			int x = myGame.getData().getPlayerOfGame().getCoordinateX();
			int y = myGame.getData().getPlayerOfGame().getCoordinateY();
			if (Math.abs(x - m.getCoordinateX()) > Math.abs(y
					- m.getCoordinateY())) {
				if (x < m.getCoordinateX()) {
					if (canMove(m, new Point((x - 1), y))) {
						moveMonsterLeft(m);
					}
				} else {
					if (canMove(m, new Point((x + 1), y))) {
						moveMonsterRight(m);
					}
				}
			} else if (Math.abs(x - m.getCoordinateX()) <= Math.abs(y
					- m.getCoordinateY())) {
				if (y < m.getCoordinateY()) {
					if (canMove(m, new Point(x, (y + 1)))) {
						moveMonsterDown(m);
					}
				} else {
					if (canMove(m, new Point(x, (y - 1)))) {
						moveMonsterUp(m);
					}
				}
			}
		} else if (moveType == FLEEING_MOVE) {
			int x = myGame.getData().getPlayerOfGame().getCoordinateX();
			int y = myGame.getData().getPlayerOfGame().getCoordinateY();
			if (Math.abs(x - m.getCoordinateX()) > Math.abs(y
					- m.getCoordinateY())) {
				if (y < m.getCoordinateY()) {
					if (canMove(m, new Point(x, (y + 1)))) {
						moveMonsterDown(m);
					}
				} else {
					if (canMove(m, new Point(x, (y - 1)))) {
						moveMonsterUp(m);
					}
				}
			} else if (Math.abs(x - m.getCoordinateX()) <= Math.abs(y
					- m.getCoordinateY())) {
				if (x < m.getCoordinateX()) {
					if (canMove(m, new Point((x + 1), y))) {
						moveMonsterRight(m);
					}
				} else {
					if (canMove(m, new Point((x - 1), y))) {
						moveMonsterLeft(m);
					}
				}
			}
		}
	}

	// allow player to hop
	public static void hopMove(Point hedgePlace, String direction) {
		if (myGame.getGameType() == Game.BUNNY_GAME && hopsLeft > NO_ITEMS) {
			hopsLeft--;
		}
	}

	public static void checkGameOver(Point newLocation) {
		for (Monster m : myGame.getData().getMonsters()) {
			if (newLocation == m.getCoordinate()
					&& !(m instanceof RunningBunny)) {
				gameOver = true;
			} else if (newLocation == m.getCoordinate()) {
				gameOver = true;
			}
		}
		if (myGame.getGameType() == Game.MOUSE_GAME) {
			if (newLocation == myGame.getData().getGameMaze().EXIT) {
				gameOver = true;
			}
		} else if (myGame.getGameType() == Game.PACMAN_GAME) {
			// MazeMap<Point,Integer> map =
			// game.getData().getGameMaze().getGameMap();
			int dotsLeft = 0;
			for (int i = 0; i < Maze.MAP_SIZE; i++) {
				for (int j = 0; j < Maze.MAP_SIZE; j++) {
					Point p = new Point(i, j);
					 if (myGame.getData().getGameMaze().getMazeItem(p) == Maze.ITEM_SPACE){
						 dotsLeft+=1;
					 }
				}
			}
			 if (dotsLeft == 0){
				 gameOver= true;
			// gameView.displayMessage("You've eaten all dots! Game Over");
			 }
		}

	}

	// move player in a direction
	public void movePlayer(String direction) {

		if (direction == UP&& canMove(myGame.getData().getPlayerOfGame(), 
 myGame.getData()
						.getPlayerOfGame().getCoordinate()) && !gameOver) {
			// might teleport here 
			int x = myGame.getData().getPlayerOfGame().getCoordinateX();
			int y = myGame.getData().getPlayerOfGame().getCoordinateY();
				Point p = new Point(x, (y - 1));

				 if(myGame.getData().getGameMaze().getMazeItem(p) ==
					 Maze.PORTAL_SPACE){
					 if(p.equals(Maze.TUNNEL1)){
						 myGame.getData().getPlayerOfGame().setCoordinateX(Maze.TUNNEL2.x);
						 myGame.getData().getPlayerOfGame().setCoordinateY(Maze.TUNNEL2.y);
					 }
					 else{
						 myGame.getData().getPlayerOfGame().setCoordinateX(Maze.TUNNEL1.x);
						 myGame.getData().getPlayerOfGame().setCoordinateY(Maze.TUNNEL1.y);
					 }
				 }
				 else if(myGame.getData().getGameMaze().getMazeItem(p) ==
					 Maze.EXIT_SPACE){
					 		gameOver  = true;
					 		myGame.getData().getPlayerOfGame().setCoordinateY(p.y);
				 }
				 else if(myGame.getData().getGameMaze().getMazeItem(p) ==
					 Maze.TRAP_SPACE){
					 		//no moves allowed on traps
				 }
				 else{
					 myGame.getData().getPlayerOfGame().setCoordinateY(p.y);
				 }
			
			checkGameOver(p);
			

		}

		else if (direction == DOWN
				&& canMove(myGame.getData().getPlayerOfGame(), myGame.getData()
						.getPlayerOfGame().getCoordinate()) && !gameOver) {

			int x = myGame.getData().getPlayerOfGame().getCoordinateX();
			int y = myGame.getData().getPlayerOfGame().getCoordinateY();
				Point p = new Point(x, (y + 1));
			 if(myGame.getData().getGameMaze().getMazeItem(p) ==
					 Maze.PORTAL_SPACE){
					 if(p.equals(Maze.TUNNEL1)){
						 myGame.getData().getPlayerOfGame().setCoordinateX(Maze.TUNNEL2.x);
						 myGame.getData().getPlayerOfGame().setCoordinateY(Maze.TUNNEL2.y);
					 }
					 else{
						 myGame.getData().getPlayerOfGame().setCoordinateX(Maze.TUNNEL1.x);
						 myGame.getData().getPlayerOfGame().setCoordinateY(Maze.TUNNEL1.y);
					 }
				 }
				 else if(myGame.getData().getGameMaze().getMazeItem(p) ==
					 Maze.EXIT_SPACE){
					 		gameOver  = true;
					 		myGame.getData().getPlayerOfGame().setCoordinateY(p.y);
				 }
				 else if(myGame.getData().getGameMaze().getMazeItem(p) ==
					 Maze.TRAP_SPACE){
					 		//no moves allowed on traps
				 }
				 else{
					 myGame.getData().getPlayerOfGame().setCoordinateY(p.y);
				 }
			checkGameOver(p);
			myGame.getData().getPlayerOfGame().setCoordinateY(y + 1);
		} else if (direction == RIGHT
				&& canMove(myGame.getData().getPlayerOfGame(), myGame.getData()
						.getPlayerOfGame().getCoordinate()) && !gameOver) {
			int x = myGame.getData().getPlayerOfGame().getCoordinateX();
			int y = myGame.getData().getPlayerOfGame().getCoordinateY();
				Point p = new Point((x + 1), y);
				if(myGame.getData().getGameMaze().getMazeItem(p) ==
						 Maze.PORTAL_SPACE){
						 if(p.equals(Maze.TUNNEL1)){
							 myGame.getData().getPlayerOfGame().setCoordinateX(Maze.TUNNEL2.x);
							 myGame.getData().getPlayerOfGame().setCoordinateY(Maze.TUNNEL2.y);
						 }
						 else{
							 myGame.getData().getPlayerOfGame().setCoordinateX(Maze.TUNNEL1.x);
							 myGame.getData().getPlayerOfGame().setCoordinateY(Maze.TUNNEL1.y);
						 }
					 }
					 else if(myGame.getData().getGameMaze().getMazeItem(p) ==
						 Maze.EXIT_SPACE){
						 		gameOver  = true;
						 		myGame.getData().getPlayerOfGame().setCoordinateX(p.x);
					 }
					 else if(myGame.getData().getGameMaze().getMazeItem(p) ==
						 Maze.TRAP_SPACE){
						 		//no moves allowed on traps
					 }
					 else{
						 myGame.getData().getPlayerOfGame().setCoordinateX(p.x);
					 }

			
			checkGameOver(p);


		} else if (direction == LEFT
				&& canMove(myGame.getData().getPlayerOfGame(), myGame.getData()
						.getPlayerOfGame().getCoordinate()) && !gameOver) {
			int x = myGame.getData().getPlayerOfGame().getCoordinateX();
			int y = myGame.getData().getPlayerOfGame().getCoordinateY();
				Point p = new Point((x - 1), y);
			if(myGame.getData().getGameMaze().getMazeItem(p) ==
					 Maze.PORTAL_SPACE){
					 if(p.equals(Maze.TUNNEL1)){
						 myGame.getData().getPlayerOfGame().setCoordinateX(Maze.TUNNEL2.x);
						 myGame.getData().getPlayerOfGame().setCoordinateY(Maze.TUNNEL2.y);
					 }
					 else{
						 myGame.getData().getPlayerOfGame().setCoordinateX(Maze.TUNNEL1.x);
						 myGame.getData().getPlayerOfGame().setCoordinateY(Maze.TUNNEL1.y);
					 }
				 }
				 else if(myGame.getData().getGameMaze().getMazeItem(p) ==
					 Maze.EXIT_SPACE){
					 		gameOver  = true;
					 		myGame.getData().getPlayerOfGame().setCoordinateX(p.x);
				 }
				 else if(myGame.getData().getGameMaze().getMazeItem(p) ==
					 Maze.TRAP_SPACE){
					 		//no moves allowed on traps
				 }
				 else{
					 myGame.getData().getPlayerOfGame().setCoordinateX(p.x);
				 }

		    
			checkGameOver(p);

		}
	}

	// MoveAction varies depending on the game
	public void moveAction(int gameType, Point location) {
		if (gameType == Game.MOUSE_GAME && doesWantToTrap()
				&& trapsLeft > NO_ITEMS) {
			placeTrap(location);
			myGame.getData().getGameMaze().setMazeItem(location,Maze.TRAP_SPACE);
			trapsLeft--;
			setWantToTrap(false);
		}

	}

	// go through the map counting the number of item spaces
	// Note: character spaces are assumed to have already used the item on them
	public void getItemsLeft() {

	}

	// check if a player can move
	public static boolean canMove(GameCharacter gamecharacter, Point p) {
		int mazeitem = myGame.getData().getGameMaze().getMazeItem(p);
		myGame.getData().getGameMaze();
		// returns true if and only if mazeItem is not a wall and point is on
		// the map
		return (mazeitem != Maze.WALL_SPACE && WithinBounds(p));

	}
	public static boolean WithinBounds(Point checkingSpot){
		if(checkingSpot.x <=9 && checkingSpot.x>=0 && checkingSpot.y <=9 && checkingSpot.y>=0){
			return true;
		}
		return false;
	}
}
